﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace SuperSprintZ
{
    public class Player : GameComponent ,IDrawableGameObject
    {
        public bool bPlayer1;
        public String playername;
        public Game1 game1;
        private PlayerController playerController;
        private SpriteEffects flippaus = SpriteEffects.None;
        public Texture2D kuva;
        public Texture2D hammerkuva1;
        public Texture2D hammerkuva2;
        public Texture2D hammerkuva5;
        public Texture2D hammerkuva6;
        public Texture2D hammerkuva7;
        public Texture2D hammerkuva8;
        public Texture2D hammertanssi1;
        public Texture2D hammertanssi2;
        public Texture2D hammertanssi3;
        public Texture2D hammertanssi4;
        public Texture2D hammertanssi5;
        public Texture2D hammertanssi6;
        public Texture2D hammertanssi7;
        public Texture2D hammertanssi8;
        public Texture2D auto;
        private int texturetimeCounter=0;
        private int textureCounter = 1;
        private int adiostimecounter = 0;
        private int adiostexture = 1;
        Color[,] varikartta1;

        public double nopeus;
        public double pausespeed;
        public float kaannosnopeus = 0.06f;
        public float skaala = 0.8f; ///(auto)kuvan koko
        public Vector2 origo;

        public float suunta;
        private Matrix rotation;
        public Vector2 pos;
        public Vector2 direction = new Vector2(0, 0);

        private Texture2D hammerkuva3;
        private Texture2D hammerkuva4;
        private Vector2 toRight;

        public BoundingSphere hitbox;
        private bool tormays = false;
        private bool middlepointcollision = false;

        private bool greencheck = false;
        private bool bluecheck = false;
        private bool redcheck = false;

        private int onlap = 0;

        public void resetPlayer()
        {
            game1.lap = 0;
            game1.written = false;
            if (game1.ratanro == 0)
            {
                pos = new Vector2(150, 135);//150,150 ekalle radalle
                if (!bPlayer1)
                {
                    pos.Y += 45;
                    pos.X -= 10;
                }
            }
            if (game1.ratanro == 1)
            {
                pos = new Vector2(150, 100);//150,150 ekalle radalle
                if (!bPlayer1)
                {
                    pos.Y += 45;
                    pos.X -= 10;
                }
            }
            suunta = 0;
            rotation = Matrix.CreateRotationZ(suunta);
            nopeus = 0;
            toRight = new Vector2((int)nopeus, 0);
            game1.resetTime();
         
        }

        public Player(Game game, bool firstplayer) : base(game)
        {
            pos = new Vector2(100, 100);
            game1 = (Game1)game;
            bPlayer1 = firstplayer;
            if (bPlayer1)
            {
                playerController = new PlayerController(this, Keys.Up, Keys.Down, Keys.Left, Keys.Right);
            }
            else
            {
                pos.X += 100;
                pos.Y += 100;
                playerController = new PlayerController(this, Keys.W, Keys.S, Keys.A, Keys.D);
            }
            // TODO: Construct any child components here
        }
        
        public Player(Game game, Texture2D h1, Texture2D h2, Texture2D h3, Texture2D h4, Texture2D h5, Texture2D h6, Texture2D h7, Texture2D h8, Texture2D autokuva,
            Texture2D t1, Texture2D t2, Texture2D t3, Texture2D t4, Texture2D t5, Texture2D t6, Texture2D t7, Texture2D t8, bool firstplayer) : base(game)
        {
            pos = new Vector2(150, 135);//150,150 ekalle radalle
            game1 = (Game1)game;
            bPlayer1 = firstplayer;
            auto = autokuva;
            hammerkuva1 = h1;
            hammerkuva2 = h2;
            hammerkuva3 = h3;
            hammerkuva4 = h4;
            hammerkuva5 = h5;
            hammerkuva6 = h6;
            hammerkuva7 = h7;
            hammerkuva8 = h8;
            hammertanssi1 = t1;
            hammertanssi2 = t2;
            hammertanssi3 = t3;
            hammertanssi4 = t4;
            hammertanssi5 = t5;
            hammertanssi6 = t6;
            hammertanssi7 = t7;
            hammertanssi8 = t8;

            kuva = hammertanssi1;
            if (bPlayer1)
            {
                playerController = new PlayerController(this, Keys.Up, Keys.Down, Keys.Left, Keys.Right);
            }
            else
            {
                //kovakoodattu auto1.png:n käyttöä varten, pitää koodata se auton valinta
                kuva = auto;
                skaala = 0.8f;
                playerController = new PlayerController(this, Keys.W, Keys.S, Keys.A, Keys.D);
                pos.Y += 45;
                pos.X -= 10;
            }
            varikartta1 = Game1.texture2DToColorArray(kuva);
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here
            origo = new Vector2(kuva.Width / 2, kuva.Height / 2);
            rotation = Matrix.CreateRotationZ(suunta);
            nopeus = 0;
            toRight = new Vector2((int)nopeus, 0);
            hitbox = new BoundingSphere(new Vector3(pos, 0),17);
            base.Initialize();
        }

        public Vector2 checkCollisionInPoint(int x, int y, Matrix matriisi1, Matrix inverseMat, int tokax, int tokay)
        {
            Color[,] tokanvarit = game1.ratavarit;
            int x2 = 0;
            int y2 = 0;
            Vector2 tekstuurikoordinaatti = new Vector2(x, y); //get the coordinate of a point within the texture
            Vector2 screenkoordinaatti = Vector2.Transform(tekstuurikoordinaatti, matriisi1); //get the pixel corresponding to that point
            Vector2 tekstuurikoordinaatti2 = Vector2.Transform(screenkoordinaatti, inverseMat); //get the point in the other texture corresponding to that pixel
            x2 = (int)tekstuurikoordinaatti2.X; //the coordinate points for the other texture
            y2 = (int)tekstuurikoordinaatti2.Y;
            if (x2 >= 0 && y2 >= 0 && x2 < tokax && y2 < tokay)
            {
                if (tokanvarit[x2, y2].B ==255 && tokanvarit[x2, y2].G ==255 && tokanvarit[x2,y2].R==255) { return screenkoordinaatti; }
                if (tokanvarit[x2, y2].G == 255) //one of the checkpoints
                {
                    greencheck = true;
                    return new Vector2(-1,-1); // no "real" collision
                }
                if (tokanvarit[x2, y2].B == 255) //one of the checkpoints
                {
                    if (greencheck)
                    {
                        bluecheck = true;
                        return new Vector2(-1,-1);
                    }
                }
                if (tokanvarit[x2, y2].R == 255) //one of the checkpoints
                {
                    if (bluecheck)
                    {
                        redcheck = true;
                        return new Vector2(-1, -1);
                    }
                }
                if (tokanvarit[x2, y2].B == 0 && tokanvarit[x2, y2].G == 0 && tokanvarit[x2, y2].R == 0) //goal line
                {
                    if (redcheck)
                    {
                        onlap++;
                        if (onlap > game1.lap)
                        {
                            game1.lap++;
                        }
                        greencheck = false;
                        bluecheck = false;
                        redcheck = false;
                        if (game1.lap == game1.lastlap)
                        {
                            game1.pause = true; //so the game freezes when the game ends
                        }
                        return new Vector2(-1, -1);
                    }
                }
            }

            return new Vector2(-1, -1);
        }

        public Vector2 collision(Matrix matriisi1, Matrix inverseMat)
        {
            Color[,] tokanvarit = game1.ratavarit;
            int ekax = varikartta1.GetLength(0);
            int ekay = varikartta1.GetLength(1);
            int tokax = tokanvarit.GetLength(0);
            int tokay = tokanvarit.GetLength(1);
            middlepointcollision = false;
            int x1 = ekax / 2;
            int y1 = ekay / 2;
            Vector2 collisionpoint = checkCollisionInPoint(x1, y1, matriisi1, inverseMat, tokax, tokay);
            if (collisionpoint.X != -1)
            {
                middlepointcollision = true;
                return collisionpoint;
            }
            x1 = 0;
            y1 = 0;
            collisionpoint = checkCollisionInPoint(x1,y1, matriisi1,inverseMat, tokax, tokay);
            if(collisionpoint.X != -1){
                return collisionpoint;
            }
            x1 = ekax - 1;
            y1 = 0;
            collisionpoint = checkCollisionInPoint(x1, y1, matriisi1, inverseMat, tokax, tokay);
            if (collisionpoint.X != -1)
            {
                return collisionpoint;
            }
            x1 = 0;
            y1 = ekay - 1;
            collisionpoint = checkCollisionInPoint(x1, y1, matriisi1, inverseMat, tokax, tokay);
            if (collisionpoint.X != -1)
            {
                return collisionpoint;
            }
            x1 = ekax - 1;
            y1 = ekay - 1;
            collisionpoint = checkCollisionInPoint(x1, y1, matriisi1, inverseMat, tokax, tokay);
            if (collisionpoint.X != -1)
            {
                return collisionpoint;
            }
            return new Vector2(-1, -1); // no collision
        }


        public bool collisionHandling(Matrix newLocation)
        {

            Vector2 cPoint = collision(newLocation, game1.ratamatriisi); //ratamatriisi is already inversed
            if (cPoint.X != -1)
            { //if there is a collision point
                if (nopeus > 0)
                {
                    nopeus = 2;
                }
                else
                {
                    if (nopeus < 0)
                    {
                        nopeus = 0;
                    }
                    else
                    {

                    }
                }
                return true;
            }
            return false;
        }
        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            playerController.Update(gameTime);
            if (!game1.pause)
            {
            if(nopeus>0)
                nopeus -= 0.02;
            toRight = new Vector2((int)nopeus, 0); //how much to the right
            rotation = Matrix.CreateRotationZ(suunta);
            direction = Vector2.Transform(toRight, rotation);
            if (bPlayer1&&nopeus>0)
            {
                adios();
            }
            else if (bPlayer1)
            {
                freshNewKicks();
             }
                Matrix newLocation = Matrix.CreateTranslation(new Vector3(-(kuva.Width / 2), -(kuva.Height / 2), 0)) * Matrix.CreateRotationZ(suunta) * Matrix.CreateScale(skaala) * Matrix.CreateTranslation((pos + direction).X, (pos + direction).Y, 0);
                tormays = collisionHandling(newLocation);
                if (!middlepointcollision)
                {
                    pos += direction;
                    hitbox.Center.X = pos.X;
                    hitbox.Center.Y = pos.Y;
                }
            }
            base.Update(gameTime);
        }

        public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(kuva, pos, null, Color.White, suunta, origo, skaala, flippaus, 0);

        }

        //for walking
        public void adios()
        {
            adiostimecounter++;
            adiostexture++;
            if (adiostexture == 8)
                adiostexture = 1;
            if (adiostimecounter > 15)
            {
                adiostimecounter = 0;
                if (adiostexture == 1)
                    kuva = hammerkuva1;
                else if (adiostexture == 2)
                    kuva = hammerkuva2;
                else if (adiostexture == 3)
                    kuva = hammerkuva3;
                else if (adiostexture == 4)
                    kuva = hammerkuva4;
                else if (adiostexture == 5)
                    kuva = hammerkuva5;
                else if (adiostexture == 6)
                    kuva = hammerkuva6;
                else if (adiostexture == 7)
                    kuva = hammerkuva7;
                else if (adiostexture == 8)
                    kuva = hammerkuva8;
            }
        }

        //for flipping mc hammer
        public void freshNewKicks()
        {
            texturetimeCounter++;
            textureCounter++;
            if (textureCounter == 8)
                textureCounter = 1;
            if (texturetimeCounter > 9)
            {
                texturetimeCounter = 0;
                if (textureCounter == 1)
                    kuva = hammertanssi1;
                else if (textureCounter == 2)
                    kuva = hammertanssi2;
                else if (textureCounter == 3)
                    kuva = hammertanssi3;
                else if (textureCounter == 4)
                    kuva = hammertanssi4;
                else if (textureCounter == 5)
                    kuva = hammertanssi5;
                else if (textureCounter == 6)
                    kuva = hammertanssi6;
                else if (textureCounter == 7)
                    kuva = hammertanssi7;
                else if (textureCounter == 8)
                    kuva = hammertanssi8;
            }           

        }

        
    }
}
